#ifndef FIBTHREAD_H_

#include "fibthreadtypes.h"

/* Manifest constants */

#define FIBTHREAD_THREADS_MAX			1024

#define FIBTHREAD_SCHED_FIFO			1
#define FIBTHREAD_SCHED_RR				2
#define FIBTHREAD_SCHED_OTHER			SCHED_RR

#define FIBTHREAD_MUTEX_NORMAL			1
#define FIBTHREAD_MUTEX_ERRORCHECK		2
#define FIBTHREAD_MUTEX_RECURSIVE		3
#define FIBTHREAD_MUTEX_DEFAULT			FIBTHREAD_MUTEX_NORMAL
#define FIBTHREAD_MUTEX_LOCK_MAX		64

/* Initializers */

#define FIBTHREAD_MUTEX_INITIALIZER		{ 0, 0, {0, 0}, {0}, 0 }
	
/* Function prototypes */

/** Basic operations **/

int fibthread_create(fibthread_t *thread, const fibthread_attr_t *attr, void *(*start_routine)(void*), void *arg);

void fibthread_exit(void *value_ptr);

int fibthread_equal(fibthread_t t1, fibthread_t t2);
fibthread_t fibthread_self(void);

/** Attribute operations **/

int fibthread_attr_destroy(fibthread_attr_t *attr);
int fibthread_attr_init(fibthread_attr_t *attr);

int fibthread_attr_getdetachstate(const fibthread_attr_t *attr,	int *detachstate);
int fibthread_attr_setdetachstate(fibthread_attr_t *attr, int detachstate);

int fibthread_attr_getstack(const fibthread_attr_t *attr, void **stack_addr, size_t *stack_size);
int fibthread_attr_setstack(fibthread_attr_t *attr, void *stack_addr,  size_t stack_size);

int fibthread_attr_getstacksize(const fibthread_attr_t *attr, size_t *stack_size);
int fibthread_attr_setstacksize(fibthread_attr_t *attr, size_t stack_size);

/** Synchronization operations **/

int fibthread_join(fibthread_t thread, void **value_ptr);

int fibthread_mutex_destroy(fibthread_mutex_t *mutex);
int fibthread_mutex_init(fibthread_mutex_t *mutex, const fibthread_mutexattr_t *attr);

int fibthread_mutex_lock(fibthread_mutex_t *mutex);
int fibthread_mutex_trylock(fibthread_mutex_t *mutex);
int fibthread_mutex_unlock(fibthread_mutex_t *mutex);

/* Signal public functions */
extern int fibthread_kill(fibthread_t thread, int sig);
extern int fibthread_sigmask(int how, const sigset_t *set, sigset_t *oset);
extern int fibthread_sigwait(const sigset_t *set, int *restrict);


/** Scheduling operations **/
int fibthread_yield(void);
void fibthread_loop(void);


/* Function prototypes that are shared between modules but shouldn't be used by public API */
extern void release_thread_resources(fibthread_struct *fibthread);
extern fibthread_struct *get_fibthread_struct_from_id(fibthread_t id);
extern int initialize(void);


#define FIBTHREAD_H_
#endif
